/*	Copyright (c) 2017 Jean-Marc VIGLINO, 
  released under the CeCILL-B license (French BSD license)
  (http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.txt).
*/

import ol_filter_Base from './Base.js'

/** Make a map or layer look like made of a set of Lego bricks.
 *  @constructor
 * @requires ol_filter
 * @extends {ol_filter_Base}
 * @param {Object} [options]
 *  @param {string} [options.img]
 *  @param {number} [options.brickSize] size of te brick, default 30
 *  @param {null | string | undefined} [options.crossOrigin] crossOrigin attribute for loaded images.
 */
var ol_filter_Lego = class olfilterLego extends ol_filter_Base {
  constructor(options) {
    options = options || {};
    super(options);

    var img = new Image();
    // Default image
    img.src = this.img[options.img] || this.img.ol3;
    img.crossOrigin = options.crossOrigin || null;

    // and pattern 
    this.pattern = {
      canvas: document.createElement('canvas')
    };

    this.setBrick(options.brickSize, img);
    this.internal_ = document.createElement('canvas');
  }
  /** Overwrite to handle brickSize
  * @param {string} key
  * @param {any} val
  */
  set(key, val) {
    super.set(key, val);
    if (key == "brickSize" && this.pattern && this.pattern.canvas.width != val) {
      this.setBrick(val);
    }
  }
  /** Set the current brick
  *	@param {number} width the pattern width, default 30
  *	@param {'brick'|'ol3'|'lego'|undefined} img the pattern, default ol3
  *	@param {string} crossOrigin
  */
  setBrick(width, img, crossOrigin) {
    width = Number(width) || 30;
    if (typeof (img) === 'string') {
      var i = new Image;
      i.src = this.img[img] || this.img.ol3;
      i.crossOrigin = crossOrigin || null;
      img = i;
    }
    if (img)
      this.pattern.img = img;
    if (!this.pattern.img.width) {
      var self = this;
      this.pattern.img.onload = function () {
        self.setBrick(width, img);
      };
      return;
    }
    this.pattern.canvas.width = this.pattern.canvas.height = width;
    this.pattern.ctx = this.pattern.canvas.getContext("2d");
    this.pattern.ctx.fillStyle = this.pattern.ctx.createPattern(this.pattern.img, 'repeat');
    this.set("brickSize", width);
    if (img)
      this.set("img", img.src);
  }
  /** Get translated pattern
  *	@param {number} offsetX x offset
  *	@param {number} offsetY y offset
  */
  getPattern(offsetX, offsetY) {
    if (!this.pattern.ctx)
      return "transparent";
    //return this.pattern.ctx.fillStyle
    var c = this.pattern.canvas;
    var ctx = this.pattern.ctx;
    var sc = c.width / this.pattern.img.width;

    ctx.save();
    ctx.clearRect(0, 0, c.width, c.height);

    ctx.scale(sc, sc);
    offsetX /= sc;
    offsetY /= sc;

    ctx.translate(offsetX, offsetY);
    ctx.beginPath();
    ctx.clearRect(-2 * c.width, -2 * c.height, 4 * c.width, 4 * c.height);
    ctx.rect(-offsetX, -offsetY, 2 * c.width / sc, 2 * c.height / sc);
    ctx.fill();
    ctx.restore();
    return ctx.createPattern(c, 'repeat');
  }
  /** Postcompose operation
  */
  postcompose(e) {
    // Set back color hue
    var ctx = e.context;
    var canvas = ctx.canvas;
    var ratio = e.frameState.pixelRatio;
    /* ol v6+
    if (e.type === 'postrender') {
      ratio = 1;
    }
    */

    ctx.save();

    // resize 
    var step = this.pattern.canvas.width * ratio;
    var p = e.frameState.extent;
    var res = e.frameState.viewState.resolution / ratio;
    var offset = [-Math.round((p[0] / res) % step), Math.round((p[1] / res) % step)];
    var ctx2 = this.internal_.getContext("2d");
    var w = this.internal_.width = canvas.width;
    var h = this.internal_.height = canvas.height;

    // No smoothing please
    ctx2.webkitImageSmoothingEnabled =
      ctx2.mozImageSmoothingEnabled =
      ctx2.msImageSmoothingEnabled =
      ctx2.imageSmoothingEnabled = false;
    var w2 = Math.floor((w - offset[0]) / step);
    var h2 = Math.floor((h - offset[1]) / step);
    ctx2.drawImage(canvas, offset[0], offset[1], w2 * step, h2 * step, 0, 0, w2, h2);
    //
    ctx.webkitImageSmoothingEnabled =
      ctx.mozImageSmoothingEnabled =
      ctx.msImageSmoothingEnabled =
      ctx.imageSmoothingEnabled = false;
    ctx.clearRect(0, 0, w, h);
    ctx.drawImage(this.internal_, 0, 0, w2, h2, offset[0], offset[1], w2 * step, h2 * step);
    /*
        for (var x=offset[0]; x<w; x+=step) for (var y=offset[1]; y<h; y+=step)
        {	if (x>=0 && y<h) ctx2.drawImage (canvas, x, y, 1, 1, x, y, step, step);
        }
        ctx.clearRect (0, 0, w,h);
        ctx.drawImage (c, 0, 0);
    */
    // Draw brick stud
    ctx.scale(ratio, ratio);
    ctx.fillStyle = this.getPattern(offset[0] / ratio, offset[1] / ratio);
    ctx.rect(0, 0, w, h);
    ctx.fill();

    ctx.restore();
  }
}

/** Image definition
*/
ol_filter_Lego.prototype.img = {
  brick: "",
  ol3: "",
  lego: ""
};

export default ol_filter_Lego
